package com.heima.admin.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.heima.admin.mapper.AdSensitiveMapper;
import com.heima.admin.service.WemediaNewsAutoScanService;
import com.heima.admin.mapper.AdChannelMapper;
import com.heima.aliyun.GreenImageScan;
import com.heima.aliyun.GreenTextScan;
import com.heima.common.exception.CustException;
import com.heima.feigns.ArticleFeign;
import com.heima.feigns.WemediaFeign;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.utils.common.SensitiveWordUtil;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {


    @Autowired
    WemediaFeign wemediaFeign;

    @Value("${file.oss.web-site}")
    String webSite;

    //文章自动审核
    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public void wemediaNewsAutoScanByMediaNewsId(Integer wmNewsId) {
        //参数校验

        //1.查询文章
        if (wmNewsId == null) {
            log.error("当前待审核 文章ID不能为空");
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID, "当前的审核ID不能为空");
        }

        ResponseResult<WmNews> wmNewsResult = wemediaFeign.findById(wmNewsId);

        if (wmNewsResult.getCode().intValue() != 0) {
            log.error("远程调用出错  {}", wmNewsResult.getErrorMessage());
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR);
        }
        WmNews wmNews = wmNewsResult.getData();

        if (wmNews == null) {
            log.error("远程调用出错 查到文章 id{}", wmNewsId);
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR);
        }

        //2.根据文章状态
        //状态为4/8 时间小于当前时间 就发布
        Short status = wmNews.getStatus();

        if ((status.shortValue() == WmNews.Status.ADMIN_SUCCESS.getCode() || status.shortValue() == WmNews.Status.SUCCESS.getCode())
                && wmNews.getPublishTime().getTime() <= System.currentTimeMillis()) {
            //发布的方法
             publishArticle(wmNews);
            return;

        }
        //3.文章状态为1 待处理
        if(status==WmNews.Status.SUBMIT.getCode()){

        //要进行审核就要对文章的所有信息进行校验 抽取 标题 内容进行文本校验。。。。图片

            Map<String,Object> contentAndImageResult= handleTextAndImages(wmNews);

            // 3.1  敏感词审核    失败   修改文章状态(2)
            boolean isSensivice = handleSensitive((String)contentAndImageResult.get("content"),wmNews);
            if(!isSensivice) return;

            // 3.2  阿里云的文本审核   失败  状态2  不确定 状态3
            boolean isTextScan = handleTextScan((String)contentAndImageResult.get("content"),wmNews);
            if(!isTextScan) return;

            // 3.3  阿里云的图片审核   失败  状态2  不确定 状态3
            Object images = contentAndImageResult.get("images");
            if(images!=null){
                boolean isImageScan =handleImageScan((List<String>)images,wmNews);
                if(!isImageScan) return;
            }

            // 4. 判断文章发布时间是否大于当前时间   状态 8
            if(wmNews.getPublishTime().after(new Date())){
                updateWmNews(wmNews,WmNews.Status.SUCCESS.getCode(),"审核成功");
                return;
            }
            // 5. 发布文章
            publishArticle(wmNews);

        }




    }

    @Autowired
    GreenImageScan greenImageScan;
    //阿里图片审核
    private boolean handleImageScan(List<String> images, WmNews wmNews) {
        boolean flag = true;
        try {
            Map map = greenImageScan.imageUrlScan(images);
            String suggestion = (String)map.get("suggestion");
            switch (suggestion){
                case "block":
                    updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"图片中有违规内容，审核失败");
                    flag = false;
                    break;
                case "review":
                    updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"图片中有不确定内容，转为人工审核");
                    flag = false;
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("阿里云图片审核出现异常 , 原因:{}",e.getMessage());
            updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"阿里云内容服务异常，转为人工审核");
            flag = false;
        }
        return flag;
    }

    @Autowired
    GreenTextScan greenTextScan;

        //阿里文章审核
    private boolean handleTextScan(String content, WmNews wmNews) {
        boolean flag = true;
        try {
            Map map = greenTextScan.greenTextScan(content);
            String suggestion = (String)map.get("suggestion");
            switch (suggestion){
                case "block":
                    updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"文本中有违规内容，审核失败");
                    flag = false;
                    break;
                case "review":
                    updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"文本中有不确定内容，转为人工审核");
                    flag = false;
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("阿里云文本审核出现异常 , 原因:{}",e.getMessage());
            updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"阿里云内容服务异常，转为人工审核");
            flag = false;
        }
        return flag;
    }


    //文章抽取 文本 图片

    private Map<String, Object> handleTextAndImages(WmNews wmNews) {

        String contentJson = wmNews.getContent(); // [{},{},{}]
        if (StringUtils.isBlank(contentJson)) {
            log.error("自动审核文章失败    文章内容为空");
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID,"文章内容为空");
        }
        List<Map> contentMaps = JSONArray.parseArray(contentJson, Map.class);
        // 1. 抽取文章中所有文本    // 家乡很美   _hmtt_   国家伟大
        String content = contentMaps.stream()
                .filter(map -> "text".equals(map.get("type")))
                .map(map -> (String) map.get("value"))
                .collect(Collectors.joining("_hmtt_"));
        content = content + "_hmtt_" + wmNews.getTitle();
        // 2. 抽取文章中所有图片   content :  全路径       images :  文件名称  + 访问前缀
        List<String> imageList = contentMaps.stream()
                .filter(map -> "image".equals(map.get("type")))
                .map(map -> (String) map.get("value"))
                .collect(Collectors.toList());
        if (StringUtils.isNotBlank(wmNews.getImages())) {
            // 按照 逗号 切割封面字符串  得到数组   基于数组得到stream   将每一条数据都拼接一个前缀 收集成集合
            List<String> urls = Arrays.stream(wmNews.getImages().split(","))
                    .map(url -> webSite + url)
                    .collect(Collectors.toList());
            imageList.addAll(urls);
        }
        // 3. 去重
        imageList = imageList.stream().distinct().collect(Collectors.toList());
        Map result = new HashMap();
        result.put("content",content);
        result.put("images",imageList);
        return result;

    }




    @Autowired
    AdSensitiveMapper adSensitiveMapper;

    private boolean handleSensitive(String content, WmNews wmNews) {
        boolean flag = true;
        // 1. 查询出数据库中的敏感词
        List<String> allSensitives = adSensitiveMapper.findAllSensitive();
        // 2. 将敏感词集合转发DFA数据模型
        SensitiveWordUtil.initMap(allSensitives);
        // 3. 检测敏感词
        Map<String, Integer> resultMap = SensitiveWordUtil.matchWords(content);
        if(resultMap!=null && resultMap.size() > 0){
            // 将文章状态改为2
            updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"内容中包含敏感词: " + resultMap);
            flag = false;
        }
        return flag;

    }


    //修改文章
    private void updateWmNews(WmNews wmNews, short status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        ResponseResult responseResult = wemediaFeign.updateWmNews(wmNews);
        if(responseResult.getCode().intValue()!=0){
            log.error(" 远程 调用修改自媒体文章接口 出错，  原因:{}     参数:{}",responseResult.getErrorMessage(),wmNews);
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR,responseResult.getErrorMessage());
        }
    }
    //发布文章

    private void publishArticle(WmNews wmNews) {

        // 1. 远程调用articleFeign接口  保存3张表的数据 保存成功获取返回的articleId
        Long articleId = saveArticle(wmNews);
        // 2. 修改wmNews 设置和article的关联  修改状态为9
        wmNews.setArticleId(articleId);
        updateWmNews(wmNews,WmNews.Status.PUBLISHED.getCode(),"发布成功");

        System.out.println("8888888888发文章");
    }

    @Autowired
    AdChannelMapper adChannelMapper;

    @Autowired
    ArticleFeign articleFeign;

    private Long saveArticle(WmNews wmNews) {


        // 封装articleDto
        ArticleDto articleDto = new ArticleDto();
        // 拷贝属性
        BeanUtils.copyProperties(wmNews,articleDto);
        articleDto.setId(wmNews.getArticleId());
        articleDto.setFlag((byte)0); // 普通文章
        articleDto.setLayout(wmNews.getType());// 布局
        articleDto.setWmUserId(wmNews.getUserId());// 用于获取作者信息
        AdChannel channel = adChannelMapper.selectById(wmNews.getChannelId());
        articleDto.setChannelName(channel.getName());
        // 远程调用文章接口
        ResponseResult<Long> saveResult = articleFeign.saveArticle(articleDto);
        if (saveResult.getCode().intValue()!=0) {
            log.error(" 远程调用保存文章方法失败  原因:{}    参数:{}",saveResult.getErrorMessage(),articleDto);
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR);
        }
        return saveResult.getData();// 返回文章id
    }

}
